﻿#pragma once
#pragma execution_character_set("UTF-8")
#include "OSGhead.h"

struct AttributeOfGroupNode//组节点 属性结构体
{
    double Reserved; //保留
};

struct AttributeOfMoveNode //运动节点 属性结构体
{
    double x;       //位置
    double y;
    double z;

    double ouler_x; //姿态（欧拉角）
    double ouler_y;
    double ouler_z;

    double x_original;       //位置
    double y_original;
    double z_original;

    double ouler_x_original; //姿态（欧拉角）
    double ouler_y_original;
    double ouler_z_original;

        double module_x; //模块化机器人位置
        double module_y;
        double module_z;

        double module_ouler_x;//模块化机器人姿态（欧拉角）
        double module_ouler_y;
        double module_ouler_z;

    osg::Vec3f vSize;//缩放比例
};

struct AttributeOfInstallNode //安装节点 属性结构体
{
    double x;       //位置
    double y;
    double z;

    double ouler_x; //姿态（欧拉角）
    double ouler_y;
    double ouler_z;

    double x_original;       //位置
    double y_original;
    double z_original;

    double ouler_x_original; //姿态（欧拉角）
    double ouler_y_original;
    double ouler_z_original;

    osg::Vec3f vSize;//缩放比例
};

struct AttributeOfModelNode //模型节点 属性结构体
{
    char   ModelPath[100];   //模型路径
    int    LightSwitch;     //灯光开关
    double Tansparent;      //透明度
    char   TexturePath[100]; //纹理路径
};

struct AttributeOfSwitchNode//组节点 属性结构体
{
    bool bShow; //保留
};

struct AttributeOfTextNode//组节点 属性结构体
{
    int DataType;						// 0:int  1:float  2:double  3:char*  4:char
    osg::Vec2s RowColumn;				//行数 列数
    std::vector<std::string> text;		//内容
    osg::Vec3f  IniPos;					//起始位置 x,y,z
    osg::Vec3f  DelPos;					//间距 x,y,z
    osg::Vec4f  color;					//文本颜色
    osg::ref_ptr<osgText::Font> font;   //字体
    int TextSize;						//大小

};

struct AttributeOfHUDNode//组节点 属性结构体
{
    HWND mhwnd;               //视口句柄
    osg::Vec4f  WindowPos;    //窗口位置
    osg::Vec4f  ProJection;   //投影矩阵
    osg::Vec4f  backcolor;    //背景颜色
    bool bTransparent;        //透明
};

struct AttributeOfLightNode//组节点 属性结构体
{
    osg::Vec3f  lightDirection;   //光线方向
    osg::Vec4f  lightPosition;    //光线位置
    osg::Vec4f  colorAmbient;     //环境光颜色
    osg::Vec4f  colorDiffuse;     //散射光颜色
    osg::Vec3f  lightPara;        //衰减指数
};

class AttributeOfTreeNode //树节点 属性结构体
{
private:
    va_list ap;
    int va_num;
    char* tmp;
public:
    DWORD NodeType;                           //节点类型
    DWORD flagAttrib;                         //属性标志
    DWORD flagUpdate;                         //更新标志

    AttributeOfGroupNode    *pGroup;          //属性指针
    AttributeOfMoveNode     *pMove;
    AttributeOfInstallNode  *pInstall;
    AttributeOfModelNode    *pModel;
    AttributeOfSwitchNode   *pSwitch;
    AttributeOfTextNode     *pText;
    AttributeOfHUDNode      *pHUD;
    AttributeOfLightNode    *pLight;

    AttributeOfTreeNode( const char* NodeType,...)
    {
        pGroup    = NULL;
        pMove     = NULL;
        pInstall  = NULL;
        pModel    = NULL;
        pSwitch   = NULL;
        pText     = NULL;
        pHUD      = NULL;
        pLight    = NULL;

        flagAttrib = NULL;
        flagUpdate = NULL;

        va_start(ap, NodeType);
        va_num = va_arg(ap, int);

        if (!strcmp(NodeType,"组节点"))   { createGroupAttribute();   return;}
        if (!strcmp(NodeType,"运动节点")) { createMoveAttribute();    return;}
        if (!strcmp(NodeType,"安装节点")) { createInstallAttribute(); return;}
        if (!strcmp(NodeType,"模型节点")) { createModelAttribute();   return;}
        if (!strcmp(NodeType,"开关节点")) { createSwitchAttribute();  return;}
        if (!strcmp(NodeType,"文本节点")) { createTextAttribute();    return;}
        if (!strcmp(NodeType,"HUD节点"))  { createHUDAttribute();     return;}
        if (!strcmp(NodeType,"光源节点")) { createLightAttribute();   return;}

        assert(FALSE);
    }

    AttributeOfTreeNode(const AttributeOfTreeNode& mAttri)
    {
        ap     = mAttri.ap;
        va_num = mAttri.va_num;
        tmp    = mAttri.tmp;

        NodeType   = mAttri.NodeType;
        flagAttrib = mAttri.flagAttrib;
        flagUpdate = mAttri.flagUpdate;

        pGroup    = NULL;
        pMove     = NULL;
        pInstall  = NULL;
        pModel    = NULL;
        pSwitch   = NULL;
        pText     = NULL;
        pHUD      = NULL;
        pLight    = NULL;

        switch(mAttri.NodeType)
        {
        case NODE_GROUP:
            pGroup = new AttributeOfGroupNode;
            *(pGroup) = *(mAttri.pGroup);
            break;
        case NODE_MOVE:
            pMove = new AttributeOfMoveNode;
            *(pMove) = *(mAttri.pMove);
            break;
        case NODE_INSTALL:
            pInstall = new AttributeOfInstallNode;
            *(pInstall) = *(mAttri.pInstall);
            break;
        case NODE_MODEL:
            pModel = new AttributeOfModelNode;
            *(pModel) = *(mAttri.pModel);
            break;
        case NODE_SWITCH:
            pSwitch = new AttributeOfSwitchNode;
            *(pSwitch) = *(mAttri.pSwitch);
            break;
        case NODE_TEXT:
            pText = new AttributeOfTextNode;
            *(pText) = *(mAttri.pText);
            break;
        case NODE_HUD:
            pHUD = new AttributeOfHUDNode;
            *(pHUD) = *(mAttri.pHUD);
            break;
        case NODE_LIGHT:
            pLight = new AttributeOfLightNode;
            *(pLight) = *(mAttri.pLight);
            break;
        default:
            assert(FALSE);
            break;
        }
    }

    ~AttributeOfTreeNode()
    {
        if(pGroup)   { delete pGroup;   pGroup   = NULL;}
        if(pMove)    { delete pMove;	pMove	 = NULL;}
        if(pInstall) { delete pInstall;	pInstall = NULL;}
        if(pModel)   { delete pModel;	pModel   = NULL;}
        if(pSwitch)  { delete pSwitch;	pSwitch  = NULL;}
        if(pText)    { delete pText;	pText	 = NULL;}
        if(pHUD)     { delete pHUD;		pHUD     = NULL;}
        if(pLight)   { delete pLight;	pLight   = NULL;}
    }

private:
    void createGroupAttribute( void )
    {
        //初始化
        NodeType = NODE_GROUP;
        pGroup = new AttributeOfGroupNode;
        pGroup->Reserved = 0;

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"保留参数"))
            {
                pGroup->Reserved = va_arg(ap, double);
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }

            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createMoveAttribute( void )
    {
        //初始化
        NodeType = NODE_MOVE;
        pMove = new AttributeOfMoveNode;
        pMove->ouler_x = 0;
        pMove->ouler_y = 0;
        pMove->ouler_z = 0;
        pMove->x = 0;
        pMove->y = 0;
        pMove->z = 0;

        pMove->ouler_x_original = 0;
        pMove->ouler_y_original = 0;
        pMove->ouler_z_original = 0;
        pMove->x_original = 0;
        pMove->y_original = 0;
        pMove->z_original = 0;

                pMove->module_ouler_x = 0;
                pMove->module_ouler_y = 0;
                pMove->module_ouler_z = 0;
                pMove->module_x = 0;
                pMove->module_y = 0;
                pMove->module_z = 0;

        pMove->vSize.set(1.0,1.0,1.0);

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"运动矩阵"))
            {
                DoubleArray* p = &va_arg(ap, DoubleArray);

                pMove->x_original = p->pType[0];
                pMove->y_original = p->pType[1];
                pMove->z_original = p->pType[2];
                pMove->ouler_x_original = p->pType[3];
                pMove->ouler_y_original = p->pType[4];
                pMove->ouler_z_original = p->pType[5];
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }

            if (!strcmp(tmp,"运动参数"))
            {
                DoubleArray* p = &va_arg(ap, DoubleArray);

                pMove->x = p->pType[0];
                pMove->y = p->pType[1];
                pMove->z = p->pType[2];
                pMove->ouler_x = p->pType[3];
                pMove->ouler_y = p->pType[4];
                pMove->ouler_z = p->pType[5];
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }

            if (!strcmp(tmp,"放缩比例"))
            {
                pMove->vSize= va_arg(ap, osg::Vec3f);
                flagAttrib |= ATRRIBUTE_03;
                continue;
            }

            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createInstallAttribute( void )
    {
        //初始化
        NodeType = NODE_INSTALL;
        pInstall = new AttributeOfInstallNode;
        pInstall->ouler_x = 0;
        pInstall->ouler_y = 0;
        pInstall->ouler_z = 0;
        pInstall->x = 0;
        pInstall->y = 0;
        pInstall->z = 0;

        pInstall->vSize.set(1.0,1.0,1.0);

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"安装矩阵"))
            {
                DoubleArray* p = &va_arg(ap, DoubleArray);

                pInstall->x = p->pType[0];
                pInstall->y = p->pType[1];
                pInstall->z = p->pType[2];
                pInstall->ouler_x = p->pType[3];
                pInstall->ouler_y = p->pType[4];
                pInstall->ouler_z = p->pType[5];
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }

            if (!strcmp(tmp,"放缩比例"))
            {
                pInstall->vSize= va_arg(ap, osg::Vec3f);
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }

            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createModelAttribute( void )
    {
        //初始化
        NodeType = NODE_MODEL;
        pModel = new AttributeOfModelNode;
        pModel->ModelPath[0]   = NULL;
        pModel->LightSwitch    = FALSE;
        pModel->Tansparent     = 1.0;
        pModel->TexturePath[0] = NULL;

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"模型路径"))
            {
                strcpy(pModel->ModelPath, va_arg(ap, const char*));
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }
            if (!strcmp(tmp,"灯光开关"))
            {
                pModel->LightSwitch = va_arg(ap, int);
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }
            if (!strcmp(tmp,"透明度"))
            {
                pModel->Tansparent = va_arg(ap, double);
                flagAttrib |= ATRRIBUTE_03;
                continue;
            }
            if (!strcmp(tmp,"纹理路径"))
            {
                strcpy(pModel->TexturePath, va_arg(ap, const char*));
                flagAttrib |= ATRRIBUTE_04;
                continue;
            }
            if (!strcmp(tmp,"可更换模型"))
            {
                va_arg(ap, const char*);	//占位用，可输入任意字符串
                flagAttrib |= ATRRIBUTE_05;
                continue;
            }
            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createSwitchAttribute( void )
    {
        //初始化
        NodeType = NODE_SWITCH;
        pSwitch = new AttributeOfSwitchNode;
        pSwitch->bShow = TRUE;


        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"模型开关"))
            {
                pSwitch->bShow = va_arg(ap, bool);
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }

            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createTextAttribute( void )
    {
        //初始化
        NodeType = NODE_TEXT;
        pText = new AttributeOfTextNode;
        pText->DataType = 4;
        pText->RowColumn.set(1,1);
        pText->IniPos.set(0.0,0.0,0.0);
        pText->DelPos.set(0.0,0.0,0.0);
        pText->color.set(0.5,0.5,0.5,1.0);
        pText->font = new osgText::Font;
        pText->font = osgText::readFontFile(OSG_FONT_SONGTI);
        pText->TextSize = 20;

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"数据类型"))
            {
                pText->DataType = va_arg(ap, int);
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }
            if (!strcmp(tmp,"行列数"))
            {
                pText->RowColumn = va_arg(ap, osg::Vec2s);
                int x = pText->RowColumn.x()*pText->RowColumn.y();
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }
            if (!strcmp(tmp,"起始位置"))
            {
                pText->IniPos = va_arg(ap, osg::Vec3f);
                flagAttrib |= ATRRIBUTE_03;
                continue;
            }
            if (!strcmp(tmp,"三维间距"))
            {
                pText->DelPos = va_arg(ap, osg::Vec3f);
                flagAttrib |= ATRRIBUTE_04;
                continue;
            }
            if (!strcmp(tmp,"颜色"))
            {
                pText->color = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_05;
                continue;
            }
            if (!strcmp(tmp,"字体"))
            {
                char *arry = va_arg(ap, char*);
                pText->font = osgText::readFontFile(arry);
                flagAttrib |= ATRRIBUTE_06;
                continue;
            }
            if (!strcmp(tmp,"放缩比例"))
            {
                pText->TextSize = va_arg(ap, int);
                flagAttrib |= ATRRIBUTE_07;
                continue;
            }
            if (!strcmp(tmp,"数据内容"))
            {
                char temp[255];
                std::string   str;
                std::wstring  wstr;


                if (0==pText->DataType)
                {
                    IntArray *arry= &va_arg(ap, IntArray);
                    if (arry->va_num != pText->RowColumn.x()*pText->RowColumn.y())
                    {
                        assert(FALSE);
                    }
                    for (int i=0;i<pText->RowColumn.x()*pText->RowColumn.y();i++)
                    {
                        sprintf(temp,"%d",arry->pType[i]);
                        str.assign(temp);
                        StringToWString(str, wstr);
                        str = convertUTF16toUTF8(wstr);
                        pText->text.push_back(str);
                    }
                }
                if (1==pText->DataType)
                {
                    FloatArray *arry = &va_arg(ap, FloatArray);
                    if (arry->va_num != pText->RowColumn.x()*pText->RowColumn.y())
                    {
                        assert(FALSE);
                    }
                    for (int i=0;i<pText->RowColumn.x()*pText->RowColumn.y();i++)
                    {
                        sprintf(temp,"%4.2f",arry->pType[i]);
                        str.assign(temp);
                        StringToWString(str, wstr);
                        str = convertUTF16toUTF8(wstr);
                        pText->text.push_back(str);
                    }
                }
                if (2==pText->DataType)
                {
                    DoubleArray *arry = &va_arg(ap, DoubleArray);
                    if (arry->va_num != pText->RowColumn.x()*pText->RowColumn.y())
                    {
                        assert(FALSE);
                    }
                    for (int i=0;i<pText->RowColumn.x()*pText->RowColumn.y();i++)
                    {
                        sprintf(temp,"%4.2f",arry->pType[i]);
                        str.assign(temp);
                        StringToWString(str, wstr);
                        str = convertUTF16toUTF8(wstr);
                        pText->text.push_back(str);

                    }
                }
                if (3==pText->DataType)
                {
                    CharPtrArray *arry = &va_arg(ap, CharPtrArray);
                    if (arry->va_num != pText->RowColumn.x()*pText->RowColumn.y())
                    {
                        assert(FALSE);
                    }
                    for (int i=0;i<pText->RowColumn.x()*pText->RowColumn.y();i++)
                    {
                        sprintf(temp,"%s",arry->pType[i]);
                        str.assign(temp);
                        StringToWString(str, wstr);
                        str = convertUTF16toUTF8(wstr);
                        pText->text.push_back(str);
                    }
                }
                if (4==pText->DataType)
                {
                    CharArray *arry = &va_arg(ap, CharArray);
                    if (arry->va_num != pText->RowColumn.x()*pText->RowColumn.y())
                    {
                        assert(FALSE);
                    }
                    for (int i=0;i<pText->RowColumn.x()*pText->RowColumn.y();i++)
                    {
                        sprintf(temp,"%c",arry->pType[i]);
                        str.assign(temp);
                        StringToWString(str, wstr);
                        str = convertUTF16toUTF8(wstr);
                        pText->text.push_back(str);
                    }
                }
                flagAttrib |= ATRRIBUTE_08;
                continue;
            }

            assert(FALSE);
        }
        /**/

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createHUDAttribute( void )
    {
        //初始化
        NodeType = NODE_HUD;
        pHUD = new AttributeOfHUDNode;
        pHUD->mhwnd = NULL;
        pHUD->WindowPos.set(0,500,0,500);
        pHUD->ProJection.set(0,500,0,500);
        pHUD->backcolor.set(0.5,0.5,0.5,1.0);
        pHUD->bTransparent = FALSE;

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"窗口句柄"))
            {
                pHUD->mhwnd = va_arg(ap, HWND);
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }
            if (!strcmp(tmp,"窗口位置"))
            {
                pHUD->WindowPos = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }
            if (!strcmp(tmp,"投影矩阵"))
            {
                pHUD->ProJection = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_03;
                continue;
            }
            if (!strcmp(tmp,"背景颜色"))
            {
                pHUD->backcolor = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_04;
                continue;
            }
            if (!strcmp(tmp,"透明度"))
            {
                pHUD->bTransparent = va_arg(ap, bool);
                flagAttrib |= ATRRIBUTE_05;
                continue;
            }
            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }
    void createLightAttribute( void )
    {
        //初始化
        NodeType = NODE_LIGHT;
        pLight = new AttributeOfLightNode;
        pLight->lightPosition.set(0.0f,0.0f,0.0f,1.0f);
        pLight->lightDirection.set(0.0f,0.0f,-1.0f);
        pLight->colorAmbient.set(1.0f,1.0f,1.0f,1.0f);
        pLight->colorDiffuse.set(1.0f,1.0f,1.0f,1.0f);
        pLight->lightPara.set(1.0f,0.0f,0.0f);

        for (int i = 0; i < va_num; i++)  // access each item in argument list
        {
            tmp = va_arg(ap, char*);

            if (!strcmp(tmp,"位置方向"))
            {
                DoubleArray* arr = &va_arg(ap, DoubleArray);

                pLight->lightPosition.set(arr->pType[0],arr->pType[1],arr->pType[2],1.0f);
                pLight->lightDirection.set(arr->pType[3],arr->pType[4],arr->pType[5]);
                flagAttrib |= ATRRIBUTE_01;
                continue;
            }
            if (!strcmp(tmp,"环境光颜色"))
            {
                pLight->colorAmbient = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_02;
                continue;
            }
            if (!strcmp(tmp,"散射光颜色"))
            {
                pLight->colorDiffuse = va_arg(ap, osg::Vec4f);
                flagAttrib |= ATRRIBUTE_03;
                continue;
            }
            if (!strcmp(tmp,"衰减指数"))
            {
                pLight->lightPara = va_arg(ap, osg::Vec3f);
                flagAttrib |= ATRRIBUTE_04;
                continue;
            }
            assert(FALSE);
        }

        va_end(ap);
        flagUpdate = flagAttrib;
    }




private:
    BOOL StringToWString(const std::string &str,std::wstring &wstr)
    {
        int nLen = (int)str.length();
        wstr.resize(nLen,L' ');

        /*该函数映射一个字符串到一个宽字符（unicode）的字符串*/
        int nResult = MultiByteToWideChar(CP_ACP,0,(LPCSTR)str.c_str(),nLen,(LPWSTR)wstr.c_str(),nLen);

        if (nResult == 0)
        {
            return FALSE;
        }

        return TRUE;
    }

    std::string convertUTF16toUTF8(const wchar_t* source, unsigned sourceLength)
    {
        if (sourceLength == 0)
        {
            return std::string();
        }

        /*该函数映射一个unicode字符串到一个多字节字符串*/
        int destLen = WideCharToMultiByte(CP_UTF8, 0, source, sourceLength, 0, 0, 0, 0);
        if (destLen <= 0)
        {
            return std::string();
        }

        std::string sDest(destLen, '\0');
        destLen = WideCharToMultiByte(CP_UTF8, 0, source, sourceLength, &sDest[0], destLen, 0, 0);

        if (destLen <= 0)
        {
            return std::string();
        }

        return sDest;
    }

    std::string convertUTF16toUTF8(const std::wstring& s){return convertUTF16toUTF8(s.c_str(), s.length());}
};

